Skip to content

Property support: Use static unmodifiable Maps for common defaults#2041

Open
matthiaso wants to merge 1 commit into
releases/26.2from
features/matthiaso/26.2/449281_improveProperySupportWithDefaultValues
Open

Property support: Use static unmodifiable Maps for common defaults#2041
matthiaso wants to merge 1 commit into
releases/26.2from
features/matthiaso/26.2/449281_improveProperySupportWithDefaultValues

Conversation

@matthiaso

Copy link
Copy Markdown
Member

Goal: Decrease memory usage when lots of property supports are in use.

449281

@matthiaso matthiaso self-assigned this Feb 20, 2026
@matthiaso matthiaso force-pushed the features/matthiaso/26.2/449281_improveProperySupportWithDefaultValues branch 7 times, most recently from 0828d57 to 4d8d0f1 Compare February 24, 2026 12:01
@matthiaso matthiaso requested a review from paolobazzi February 24, 2026 18:43
Goal: Decrease memory usage when lots of property supports are in use.

449281
@paolobazzi paolobazzi force-pushed the features/matthiaso/26.2/449281_improveProperySupportWithDefaultValues branch from 4d8d0f1 to 7a101bf Compare June 25, 2026 14:42

@paolobazzi paolobazzi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See inputs for minor improvements

public class DefaultValueMapTest {

@Test
public void testIsEmptyAndSize() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add test methods for non-covered parts:

  • Constructor using startEmpty=true
  • containsKey
  • containsValue
  • size
  • isEmpty

}.init();
P_DefaultValueMap lastDefaultValueMap = m_propertySupportFactory.getLastDefaultValueMaps().getFirst();
Map<String, Object> additionalValues = lastDefaultValueMap.getAdditionalValues();
assertEquals(Set.of(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a message like 'found additional initally set property, check factory method, see org.eclipse.scout.rt.client.ui.BasicPropertySupportFactory'

/**
* Factory to create a {@link BasicPropertySupport} for any {@link AbstractPropertyObserver}.
* <p>
* The newly created property support will always be backed by an underlying empty {@link Map}, this is either a regular {@link HashMap} or a {@link DefaultValueMap} which is size-optimized for the specific property observer if it is filled

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

underlaying map is not per-se empty if it was initialized with default values?

}

protected Map<String, Object> createDefaultValueMapForAbstractButton() {
HashMap<String, Object> defaultValues = new HashMap<>(createDefaultValueMapForAbstractFormField());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does the methods mix up two init pattern (new ImmutablePair() vs. defaultValues.put) ?
-> use defaultValues.put() for all?

public BasicPropertySupport createFor(AbstractPropertyObserver holder) {
// order matters
Map<String, Object> defaultValues = switch (holder) {
case AbstractMenu ignored -> m_defaultValuesByClass.computeIfAbsent(AbstractMenu.class, k -> createDefaultValueMapForAbstractMenu());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use _ instead of ignored?

boolean additionalValuesContainsKey = m_additionalValues.containsKey(key);
if (m_defaultValues.containsKey(key)) {
if (isDefaultValue(key, value)) { // must be same, equals would not be sufficient
return additionalValuesContainsKey

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code is hard to read -> split into several methods or use if then else on separate lines and prepending a javadoc indicating which case is handled

e.g.:

  @Override
  public Object put(String key, Object value) {
    boolean additionalValuesContainsKey = m_additionalValues.containsKey(key);
    if (m_defaultValues.containsKey(key)) {
      if (isDefaultValue(key, value)) { // must be same, equals would not be sufficient
        if (additionalValuesContainsKey) {
          Object removedValue = m_additionalValues.remove(key);
          return removedValue != REMOVED_MARKER ? removedValue : null;
        } else {
          return m_defaultValues.get(key);
        }
      }
      else if (!additionalValuesContainsKey) {
        m_additionalValues.put(key, value);
        return m_defaultValues.get(key); // load previous value from default values (if any)
      }
    }
//....


@Override
public Set<Entry<String, Object>> entrySet() {
return new AbstractSet<>() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extract into protected sub-class for maintenance/override?


import org.junit.Test;

public class DefaultValueMapTest {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check for missing coverage in DefaultValueMap:

  • Iterator/EntrySet.next()
  • Iterator/EntrySet.remove()
  • Iterator/EntrySet.size
  • Iterator/EntrySet.isEmpty


import org.junit.Test;

public class DefaultValueMapTest {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need a platformtestrunner if no BEANS are used?

mapWithA.put("B", 2);
mapWithA.put("C", 3);

mapWithA.keySet().remove("A");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suppress warnings

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants